home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / windows5 / wintidy.zip / WINPAS.ZIP / TIDYWINB.PAS < prev    next >
Pascal/Delphi Source File  |  1992-11-01  |  8KB  |  258 lines

  1. UNIT TidyWinB;
  2. (**) INTERFACE (**)
  3. USES WinTypes, WinProcs, Strings, Win31, TidyWinA,
  4. {$IFDEF VER70} ODialogs, OWindows, Objects;
  5. {$ELSE} WObjects; {$ENDIF}
  6. CONST
  7.   ServerName      = 'PROGMAN';
  8.   TopicName       = 'PROGMAN';
  9.   GroupSect       = 'Groups';
  10.   ProgmanSect     = 'Progman.Itself';
  11.     {DDE constants}
  12.   fResponse = $1000;
  13.   fRelease  = $2000;
  14.   reserved  = $4000;
  15.   fAckReq   = $8000;
  16. TYPE
  17.   PTidyWindowB = ^TTidyWindowB;
  18.   TTidyWindowB = OBJECT(TTidyWindowA)
  19.     LinkedToPM       : Boolean;
  20.     IniName          : PChar;
  21.     TAserver,
  22.     TAtopic, TAGroup : TAtom;
  23.     CurrGrp          : Word;
  24.     CONSTRUCTOR Init(AParent : PWindowsObject; AName : PChar);
  25.     DESTRUCTOR Done; Virtual;
  26.     FUNCTION CanClose : Boolean; Virtual;
  27.     PROCEDURE SaveLayout;
  28.     PROCEDURE InitDDEConversation;
  29.     PROCEDURE Converse; Virtual;
  30.     PROCEDURE wmDDEAck(VAR Msg : TMessage); Virtual
  31.       wm_First + wm_DDE_Ack;
  32.     PROCEDURE wmDDEData(VAR Msg : TMessage); Virtual
  33.       wm_First + wm_DDE_Data;
  34.     PROCEDURE wmDDETerminate(VAR Msg : TMessage); Virtual
  35.       wm_First + wm_DDE_Terminate;
  36.   END;
  37.  
  38. (**) IMPLEMENTATION (**)
  39.   CONSTRUCTOR TTidyWindowB.Init(AParent : PWindowsObject;
  40.     AName : PChar);
  41.   BEGIN
  42.     TTidyWindowA.Init(AParent, AName);
  43.     LinkedToPM := FALSE;
  44.   END;
  45.  
  46.   DESTRUCTOR TTidyWindowB.Done;
  47.   BEGIN
  48.     IF LinkedToPM THEN PostMessage(PMWindow, wm_DDE_Terminate,
  49.       hWindow, 0);
  50.     TTidyWindowA.Done;
  51.   END;
  52.  
  53.   FUNCTION TTidyWindowB.CanClose : Boolean;
  54.   BEGIN
  55.     IF LinkedToPM THEN
  56.       BEGIN
  57.         CanClose := FALSE;
  58.         IF NOT Quiet THEN MessageBeep(mb_IconInformation);
  59.         MessageBox(hWindow, 'Patience - DDE conversation still '+
  60.           'in progress.', 'WINTIDY', mb_OK + mb_IconInformation);
  61.       END
  62.     ELSE CanClose := TRUE;
  63.   END;
  64.  
  65.   PROCEDURE TTidyWindowB.SaveLayout;
  66.   VAR N : Word;
  67.  
  68.     PROCEDURE ClearIniFile;
  69.     CONST bSize = MaxGroups*50; {est. max 50 chars per name}
  70.     VAR SecBuff, P : PChar;
  71.     BEGIN
  72.       GetMem(SecBuff, bSize);
  73.        {fill SecBuff with all keys from Groups section, separated by
  74.         #0 and ending with a double #0} 
  75.       GetPrivateProfileString(GroupSect, NIL, '', SecBuff,
  76.         bSize, IniName);
  77.       P := SecBuff;
  78.         {"walk" P through the list}
  79.       WHILE P[0] <> #0 DO
  80.         BEGIN
  81.             {Clear items section for this group}
  82.           WritePrivateProfileString(P, NIL, NIL, IniName);
  83.           P := StrEnd(P) + 1;
  84.         END;
  85.       FreeMem(SecBuff, bSize);
  86.         {Clear the existing Groups section}
  87.       WritePrivateProfileString(GroupSect, NIL, NIL, IniName);
  88.         {Clear the ProgMan section}
  89.       WritePrivateProfileString(ProgmanSect, NIL, NIL,
  90.         IniName);
  91.     END;
  92.  
  93.     PROCEDURE WriteOneLocation(IsGroup : Boolean; H : HWnd);
  94.     CONST
  95.       nBSize = 80;
  96.       tBSize = 60; 
  97.     VAR
  98.       NameBuf : ARRAY[0..nBSize] OF Char;
  99.       Sect    : PChar;
  100.       TWP     : TWindowPlacement;
  101.       TWPbuf  : ARRAY[0..tBSize] OF Char;
  102.     BEGIN
  103.       IF IsGroup THEN
  104.         BEGIN
  105.           GetWindowText(H, NameBuf, nBSize);
  106.           Sect := GroupSect;
  107.         END
  108.       ELSE
  109.         BEGIN
  110.           StrCopy(NameBuf, 'Placement');
  111.           Sect := ProgmanSect;
  112.         END;
  113.         {Must set TWP.length before calling GetWindowPlacement}
  114.       TWP.length := SizeOf(TWP);
  115.       GetWindowPlacement(H, @TWP);
  116.       wvsprintf(TWPBuf, '%u;%u;%u,%u;%u,%u;%u,%u,%u,%u', TWP.flags);
  117.       WritePrivateProfileString(Sect, NameBuf, TWPBuf, IniName);
  118.     END;
  119.  
  120.   BEGIN
  121.     IF pmWindow = 0 THEN Exit;
  122.     OldCur := SetCursor(LoadCursor(0, idc_Wait));
  123.     SetCapture(hWindow);
  124.     ClearIniFile;
  125.     GetGroupHandles;
  126.       {write location data for each group window, and ProgMan too}
  127.     FOR N := 1 TO THA[0] DO WriteOneLocation(TRUE, THA[N]);
  128.     WriteOneLocation(FALSE, PMWindow);
  129.     CurrGrp := 0;
  130.     InitDDEConversation;
  131.   END;
  132.  
  133.   PROCEDURE TTidyWindowB.InitDDEConversation;
  134.   BEGIN
  135.       {initiate a DDE conversation with ProgMan}
  136.     TAserver := GlobalAddAtom(ServerName);
  137.     TATopic  := GlobalAddAtom(TopicName);
  138.       {ProgMan will respond with wm_DDE_Ack}
  139.     SendMessage(pmWindow, wm_DDE_Initiate, hWindow,
  140.       MakeLong(TAserver, TAtopic));
  141.     GlobalDeleteAtom(TAtopic);
  142.     GlobalDeleteAtom(TAserver);
  143.   END;
  144.  
  145.   PROCEDURE TTidyWindowB.wmDDEAck(VAR Msg : TMessage);
  146.     {Should receive one Ack upon initiating conversation.}
  147.   BEGIN
  148.     IF NOT LinkedToPM THEN
  149.       BEGIN
  150.         LinkedToPM := TRUE;
  151.         TAserver   := Msg.LParamLo;
  152.         TAtopic    := Msg.LParamHi;
  153.         PMWindow   := Msg.wParam;
  154.         IF TAserver <> 0 THEN GlobalDeleteAtom(TAserver);
  155.         IF TAtopic  <> 0 THEN GlobalDeleteAtom(TAtopic);
  156.         Converse;
  157.       END
  158.     ELSE
  159.       BEGIN
  160.         IF (Msg.LParamLo AND dde_Ack) <> dde_Ack THEN
  161.           BEGIN
  162.             IF NOT Quiet THEN MessageBeep(mb_IconStop);
  163.             MessageBox(hWindow, 'Program Manager does not'+
  164.               ' acknowledge command', 'ERROR',
  165.               mb_Ok + mb_IconStop);
  166.             SetCursor(OldCur);
  167.             ReleaseCapture;
  168.           END;
  169.         GlobalDeleteAtom(Msg.lParamHi);
  170.       END;
  171.   END;
  172.  
  173.   PROCEDURE TTidyWindowB.Converse;
  174.   CONST nBSize = 80;
  175.   VAR NameBuf : ARRAY[0..nBSize] OF Char;
  176.   BEGIN
  177.     Inc(CurrGrp);
  178.     IF CurrGrp <= THA[0] THEN
  179.       BEGIN
  180.         GetWindowText(THA[CurrGrp], NameBuf, nBSize);
  181.         TAGroup := GlobalAddAtom(NameBuf);
  182.           {ProgMan will respond with wm_DDE_Data}
  183.         PostMessage(PMWindow, wm_DDE_Request, hWindow,
  184.           MakeLong(cf_Text, TAGroup));
  185.       END
  186.     ELSE
  187.       BEGIN
  188.         IF NOT Quiet THEN MessageBeep(mb_IconInformation);
  189.         MessageBox(hWindow, 'Layout has been saved in INI file',
  190.           IniName, mb_Ok + mb_IconInformation);
  191.         PostMessage(PMWindow, wm_DDE_Terminate, hWindow, 0);
  192.         SetCursor(OldCur);
  193.         ReleaseCapture;
  194.       END;
  195.   END;
  196.  
  197.   PROCEDURE TTidyWindowB.wmDDEData(VAR Msg : TMessage);
  198.   VAR
  199.     PTD              : PDDEData;
  200.     Release          : Boolean;
  201.     PData, GrpName,
  202.     ItemP, NextItem,
  203.     NameP            : PChar;
  204.     Len, M           : Word;
  205.   BEGIN
  206.     PTD := GlobalLock(Msg.lParamLo);
  207.     Release := PTD^.Flags AND fRelease > 0;
  208.     GlobalDeleteAtom(Msg.lParamHi);
  209.     PData   := @PTD^.Value;
  210.     Len     := StrLen(PData);
  211.       {replace CR/LF with #0#0, so can use StrEnd to "walk" the list}
  212.     FOR M := 0 TO pred(Len) DO
  213.       IF (PData[M] = #13) OR (PData[M] = #10) THEN
  214.         PData[M] := #0;
  215.       {point ItemP to first line of ITEM data, after GROUP data}
  216.     ItemP := StrEnd(PData)+2;
  217.       {point GrpName past initial quotemark...}
  218.     GrpName := PData+1;
  219.       {... and chop it off at next quotemark}
  220.     StrScan(GrpName, '"')^ := #0;
  221.       {If ItemP empty, there *ARE* no items}
  222.     IF ItemP[0] = #0 THEN
  223.       BEGIN
  224.         IF NOT Quiet THEN MessageBeep(mb_IconInformation);
  225.         MessageBox(hWindow, 'Note: Group contains NO program items',
  226.           GrpName, mb_Ok + mb_IconInformation);
  227.       END
  228.     ELSE
  229.         {now record the individual item data}
  230.       REPEAT
  231.           {Note location of NEXT item before we chop up this item}
  232.         NextItem := StrEnd(ItemP)+2;
  233.         NameP := ItemP+1; {skip initial quotemark}
  234.         ItemP := StrScan(NameP, '"') + 2;
  235.           {NameP points to item name - chop it off at quote}
  236.         StrScan(NameP,'"')^ := #0;
  237.           {ItemP points at path after quoted name.  skip over three
  238.            commas to reach location data}
  239.         ItemP := StrScan(ItemP, ',')+1;
  240.         ItemP := StrScan(ItemP, ',')+1;
  241.         ItemP := StrScan(ItemP, ',')+1;
  242.           {insert #0 at 2nd comma}
  243.         StrScan(StrScan(ItemP, ',')+1, ',')^ := #0;
  244.           {record item name as key, location as value}
  245.         WritePrivateProfileString(GrpName, NameP, ItemP, IniName);
  246.         ItemP := NextItem;
  247.       UNTIL ItemP-PData >= Len;
  248.     GlobalUnlock(Msg.lParamLo);
  249.     IF Release THEN GlobalFree(Msg.lParamLo);
  250.     Converse;
  251.   END;
  252.  
  253.   PROCEDURE TTidyWindowB.wmDDETerminate(VAR Msg:TMessage);
  254.   BEGIN
  255.     LinkedToPM := FALSE;
  256.   END;
  257. END.
  258.